package com.graduation.project.service.process.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.graduation.project.entity.dto.task.ListTaskDTO;
import com.graduation.project.entity.dto.assignmentBook.SaveOrUpdateAssignmentDTO;
import com.graduation.project.entity.dto.UpdateStatusDTO;
import com.graduation.project.entity.other.LoginUser;
import com.graduation.project.entity.po.Assignment;
import com.graduation.project.entity.po.Schedule;
import com.graduation.project.entity.po.Task;
import com.graduation.project.entity.vo.*;
import com.graduation.project.entity.vo.task.ListTaskVO;
import com.graduation.project.enums.ResultCodeEnum;
import com.graduation.project.mapper.process.AssignmentBookMapper;
import com.graduation.project.mapper.process.ListAssignmentBookMapper;
import com.graduation.project.mapper.process.ScheduleMapper;
import com.graduation.project.mapper.topic.TaskMapper;
import com.graduation.project.service.process.AssignmentBookService;
import com.graduation.project.service.process.OpenReportService;
import com.graduation.project.service.process.ScheduleService;
import com.graduation.project.utils.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class AssignmentBookServiceImpl extends ServiceImpl<AssignmentBookMapper, Assignment> implements AssignmentBookService {

    @Autowired
    private AssignmentBookMapper assignmentBookMapper;
    @Autowired
    private ListAssignmentBookMapper listAssignmentBookMapper;
    @Autowired
    private TaskMapper taskMapper;
    @Autowired
    private ScheduleService scheduleService;
    @Autowired
    private ScheduleMapper scheduleMapper;
    @Autowired
    private OpenReportService openReportService;

    @Override
    public ResultUtil<?> getTaskOptions() {
        // 获取个人信息
        UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authenticationToken.getPrincipal();
        String userCode = loginUser.getUser().getUserCode();

        // 查找出自本人（拥有新增任务书权限）的所有已通过审核的课题（本人发布的课题）,且未提交任务书的课题
        LambdaQueryWrapper<Task> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Task::getAdviserCode, userCode)
                .eq(Task::getAuditStatus, 2);
        List<Task> tasks = taskMapper.selectList(lambdaQueryWrapper);

        List<ListTaskOptionsVO> listTaskOptionsVOS = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(tasks)) {
            listTaskOptionsVOS = tasks.stream()
                    .filter(task -> {
                        LambdaQueryWrapper<Assignment> queryAssignment = new LambdaQueryWrapper<>();
                        queryAssignment.eq(Assignment::getTaskId, task.getId());
                        Assignment assignment = assignmentBookMapper.selectOne(queryAssignment);
                        if (ObjectUtil.isEmpty(assignment)) {
                            return true;
                        }
                        return false;
                    })
                    .map(task -> {
                        ListTaskOptionsVO listTaskOptionsVO = new ListTaskOptionsVO();
                        BeanUtil.copyProperties(task, listTaskOptionsVO);
                        return listTaskOptionsVO;
                    })
                    .collect(Collectors.toList());
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS, listTaskOptionsVOS);
    }

    @Override
    public ResultUtil<?> getAssignmentBookDetails(Long id) {
        if (ObjectUtil.isEmpty(id)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "参数不能为空");
        }
        // 判断任务书是否存在
        Assignment assignment = assignmentBookMapper.selectOne(new LambdaQueryWrapper<Assignment>().eq(Assignment::getId, id));
        if (ObjectUtil.isEmpty(assignment)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "任务书不存在");
        }
        AssignmentDetailsVO output = new AssignmentDetailsVO();
        BeanUtil.copyProperties(assignment, output);
        // 查询任务书对应的计划进度
        LambdaQueryWrapper<Schedule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Schedule::getAssignmentId, assignment.getId());
        List<Schedule> scheduleList = scheduleMapper.selectList(queryWrapper);

        List<ScheduleDataVO> scheduleDataVOList = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(scheduleList)) {
            scheduleDataVOList = scheduleList.stream()
                    .map(schedule -> {
                        ScheduleDataVO scheduleDataVO = new ScheduleDataVO();
                        List<String> timeList = new ArrayList<>();
                        timeList.add(schedule.getStartTime());
                        timeList.add(schedule.getEndTime());

                        scheduleDataVO.setMainContent(schedule.getMainContent());
                        scheduleDataVO.setTimeArrangement(timeList);
                        scheduleDataVO.setScheduleRemark(schedule.getScheduleRemark());
                        return scheduleDataVO;
                    })
                    .collect(Collectors.toList());
        }
        output.setScheduleDataList(scheduleDataVOList);

        return ResultUtil.Success(ResultCodeEnum.SUCCESS, output);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> addAssignmentBook(SaveOrUpdateAssignmentDTO input) {
        // 判断此课题任务书是否已存在
        LambdaQueryWrapper<Assignment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Assignment::getTaskId, input.getTaskId());
        Assignment res = assignmentBookMapper.selectOne(lambdaQueryWrapper);
        if (ObjectUtil.isNotEmpty(res)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "课题任务书已存在");
        }
        // 新增任务书，返回任务书id
        Assignment assignment = new Assignment();
        BeanUtil.copyProperties(input, assignment);
        try {
            assignmentBookMapper.insert(assignment);
            // 新增计划进度
            if (CollUtil.isNotEmpty(input.getScheduleDataList())) {
                Collection<Schedule> scheduleList = input.getScheduleDataList().stream()
                        .map(item -> {
                            Schedule schedule = new Schedule();
                            schedule.setMainContent(item.getMainContent());
                            schedule.setStartTime(item.getTimeArrangement().get(0));
                            schedule.setEndTime(item.getTimeArrangement().get(1));
                            schedule.setScheduleRemark(item.getScheduleRemark());
                            schedule.setAssignmentId(assignment.getId());
                            return schedule;
                        })
                        .collect(Collectors.toList());

                scheduleService.saveBatch(scheduleList);
            }
        }catch (Exception e) {
            throw new RuntimeException("新增任务书失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "新增成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> updateAssignmentBook(SaveOrUpdateAssignmentDTO saveOrUpdateAssignmentDTO) {
        // 判断此课题任务书是否存在
        LambdaQueryWrapper<Assignment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Assignment::getTaskId, saveOrUpdateAssignmentDTO.getTaskId());
        Assignment res = assignmentBookMapper.selectOne(lambdaQueryWrapper);
        if (ObjectUtil.isEmpty(res)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "课题任务书不存在");
        }
        // 判断此课题任务书是否已审核通过
        if (res.getAuditStatus() == 1) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "课题任务书已审核通过");
        }

        Assignment assignment = new Assignment();
        BeanUtil.copyProperties(saveOrUpdateAssignmentDTO, assignment);
        // 重置任务书状态
        assignment.setAuditStatus(0);
        // 重置审核意见
        assignment.setAuditIdea("");

        LambdaQueryWrapper<Schedule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Schedule::getAssignmentId, saveOrUpdateAssignmentDTO.getId());

        try {
            // 修改任务书
            this.updateById(assignment);
            // 清空任务书对应的计划进度
            scheduleMapper.delete(queryWrapper);
            // 新增计划进度
            if (ObjectUtil.isNotEmpty(saveOrUpdateAssignmentDTO.getScheduleDataList())) {
                Collection<Schedule> scheduleList = saveOrUpdateAssignmentDTO.getScheduleDataList().stream()
                        .map(item -> {
                            Schedule schedule = new Schedule();
                            schedule.setMainContent(item.getMainContent());
                            schedule.setStartTime(item.getTimeArrangement().get(0));
                            schedule.setEndTime(item.getTimeArrangement().get(1));
                            schedule.setScheduleRemark(item.getScheduleRemark());
                            schedule.setAssignmentId(saveOrUpdateAssignmentDTO.getId());
                            return schedule;
                        })
                        .collect(Collectors.toList());
                scheduleService.saveBatch(scheduleList);
            }
        }catch (Exception e) {
            throw new RuntimeException("修改失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "修改成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> deleteAssignmentBook(Long id) {
        if (ObjectUtil.isEmpty(id)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "参数不能为空");
        }
        // 判断删除数据是否存在
        Assignment assignment = assignmentBookMapper.selectOne(new LambdaQueryWrapper<Assignment>().eq(Assignment::getId, id));
        if (ObjectUtil.isEmpty(assignment)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "课题任务书不存在");
        }
        // 如果是已通过审核数据则不能删除
        if (assignment.getAuditStatus() == 1) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "任务书已通过审核不能删除");
        }
        try {
            // 删除任务书计划进度
            scheduleMapper.delete(new LambdaQueryWrapper<Schedule>().eq(Schedule::getAssignmentId, id));
            // 删除任务书
            assignmentBookMapper.deleteById(assignment);
        } catch (Exception e) {
            throw new RuntimeException("删除失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "删除成功");
    }

    @Override
    public ResultUtil<?> listAssignmentBookByCondition(ListTaskDTO input) {
        IPage<ListTaskVO> page = new Page<>();
        page.setCurrent(input.getCurrentPage());
        page.setSize(input.getPageSize());
        IPage<ListAssignmentBookVO> data = listAssignmentBookMapper.listAssignmentBookByCondition(page, input);

        Map<String, Object> map = new HashMap<>();
        map.put("listAssignmentBookVo", data.getRecords());
        map.put("total", data.getTotal());
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "查询成功", map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> auditAssignmentBook(UpdateStatusDTO input) {
        // 判断此课题任务书是否存在,若存在判断是否是待审核状态
        Assignment assignment = assignmentBookMapper.selectOne(new LambdaQueryWrapper<Assignment>().eq(Assignment::getId, input.getId()));
        if (ObjectUtil.isEmpty(assignment)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "任务书不存在");
        }
        if (assignment.getAuditStatus() != 0) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "任务书已被审核");
        }
        assignment.setAuditStatus(input.getStatus());
        assignment.setAuditIdea(input.getIdea());
        try {
            assignmentBookMapper.updateById(assignment);
        }catch (Exception e) {
            throw new RuntimeException("审核失败");
        }
        // 如果任务书审核通过，新增一条开题报告数据
        if (input.getStatus() == 1) {
            try {
                openReportService.createOpenReport(assignment.getTaskId());
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "审核成功");
    }
}
